package ginplus

import (
	"gpt-api/pkg/util"
	"net/http"

	"github.com/gin-gonic/gin"
	"gpt-api/framework/codes"
	myerr "gpt-api/framework/errors"
	"gpt-api/framework/log"
)

type HandlerFunc func(c *gin.Context) error

func Wrapper(handler HandlerFunc) func(c *gin.Context) {
	return func(c *gin.Context) {
		handler(c)
	}
}

// ReplyError 响应自定义错误
func ReplyError(c *gin.Context, code codes.Code, err error) error {
	message := util.GetTransData(Language(c), code)
	return replyError(c, myerr.Wrap(err, code, message))
}

// ReplyInternalError ReplyError 系统异常
func ReplyInternalError(c *gin.Context, err error) error {
	return replyError(c, myerr.InternalServerError(Language(c), err))
}

// ReplyBadRequest 参数错误
func ReplyBadRequest(c *gin.Context, err error) error {
	return replyError(c, myerr.BadRequest(Language(c), err))
}

// ReplyUnauthorized Unauthorized generates a 401 error.
func ReplyUnauthorized(c *gin.Context, err error) error {
	return replyError(c, myerr.Unauthorized(Language(c), err))
}

// ReplyForbidden Forbidden generates a 403 error.
func ReplyForbidden(c *gin.Context, err error) error {
	return replyError(c, myerr.Forbidden(Language(c), err))
}

// ReplyNotFound generates a 403 error.
func ReplyNotFound(c *gin.Context, err error) error {
	return replyError(c, myerr.NotFound(Language(c), err))
}

// ReplyJSON Success generates a 0 code response.
func ReplyJSON(c *gin.Context, data interface{}) error {
	return replySuccess(c, data)
}

type Response struct {
	Code    codes.Code  `json:"code"`
	Data    interface{} `json:"data"`
	Message string      `json:"message"`
}

func ReplySuccessMap(ctx *gin.Context, data map[string]interface{}) error {
	if data == nil {
		data = map[string]interface{}{}
	}

	data["code"] = codes.OK
	if _, ok := data["message"]; !ok {
		data["message"] = ""
	}

	ctx.JSON(http.StatusOK, &data)
	return nil
}

func replySuccess(ctx *gin.Context, data interface{}) error {
	if data == nil {
		data = struct{}{}
	}
	ctx.JSON(http.StatusOK, &Response{
		Code: codes.OK,
		Data: data,
	})
	return nil
}

func replyError(ctx *gin.Context, err error) error {
	var resp Response
	httpStatus := http.StatusOK
	if err != nil {
		log.Error("reply err", log.String("x-request-id", RequestID(ctx)), log.Errval(err))
		if er, ok := err.(*myerr.Error); ok {
			switch er.Code {
			case codes.BadRequest:
				httpStatus = http.StatusBadRequest
			case codes.InternalServerError:
				httpStatus = http.StatusInternalServerError
			}
			resp.Code = er.Code
			resp.Message = er.Detail
		} else {
			resp.Code = codes.Unknown
			resp.Message = err.Error()
		}
	}
	ctx.JSON(httpStatus, &resp)

	return nil
}
